package com.jjh.winterframework.core;

import com.jjh.winterframework.annatation.Autowired;
import com.jjh.winterframework.annatation.Component;
import com.jjh.winterframework.util.WinterUtils;

import java.io.File;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 *  Autowired 注解解析器
 * 目的是为了自动注入
 * 原理:
 *   先拿到注解了@Componet的类文件，
 *   然后判断该类中的属性上是否被@Autowired注解标记，
 *   如果标记了，那么就根据这个属性的类型从beanMap中
 *   查找，找到了该类型的bean对象，就把该对象赋值给该
 *   属性
 * @author JJH
 */
public class AutoWiredProcess {


    public AutoWiredProcess(){
        autowiredProcess();
    }


    /**
     * 解析属性上的autowired注解，依赖注入
     *
     */
    public void autowiredProcess() {
      //先把@componet注解的类找到再说
        List<File> comFiles = WinterUtils.getClassFileByAnnatation(Component.class);
        Map<String, Object> beans = ApplicationContext.getBeans();

        for (File comFile : comFiles) {
            //获取属性
            String className = WinterUtils.getClassName(comFile.getPath());
            Class<?> aClass = null;
            try {
                aClass = Class.forName(className);
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            }
            Field[] fields = aClass.getDeclaredFields();
            for (Field field : fields) {
               if(field.getAnnotation(Autowired.class)!=null){
                   //属性上有@autowired注解，
                   //我们从map集合中查找它所需要的bean
                   field.setAccessible(true);
                   beans.forEach((id,bean)->{
                       if(className.endsWith(bean.getClass().getName())){
                           //类名对住的时候，就该来给他依赖注入了
                           Field[] beanfields = bean.getClass().getDeclaredFields();
                           for (Field beanfield : beanfields) {
                               Class<?> type = beanfield.getType();
                               beans.forEach((k,v)->{
                                   if(type.equals(v.getClass())){
                                       try {
                                           beanfield.setAccessible(true);
                                           beanfield.set(bean,v);
                                       } catch (IllegalAccessException e) {
                                           throw new RuntimeException(e);
                                       }
                                   }
                               });
                           }
                       }
                   });
               }
            }

        }


    }








}
